#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <sys/socket.h>
#include <arpa/inet.h>

#define MAX_CLIENTS 5
#define SERVER_PORT 22125
#define LISTEN_PORT 12121
#define MAX_BUFFER_SIZE 1024
int server_socket;
int listen_socket;
int serverForInfo[MAX_CLIENTS];
char session_header[MAX_CLIENTS][20];
int indexOfClient = 0;
void handle(int client_sock, char buffer[], int server_sock)
{
    char *method, *url, *DianTP_version, *cseq_header;
    char response[MAX_BUFFER_SIZE] = {0};
    char request[MAX_BUFFER_SIZE] = {0};

    method = strtok(buffer, " ");
    url = strtok(NULL, " ");
    DianTP_version = strtok(NULL, "\r\n");
    cseq_header = strtok(NULL, "\r\n");
    if (strcmp(method, "OPTIONS") == 0)
    {
        sprintf(response, "DianTP/0.5 200 OK\r\nCSeq: 1\r\nPublic methods: OPTIONS, SETUP, PLAY, TEARDOWN\r\n\r\n");
        printf("The information send to the client:\n%s", response);
        send(client_sock, response, strlen(response), 0);
    }
    else if (strcmp(method, "SETUP") == 0)
    {
        char *clientInfo = strtok(NULL, "\r\n");
        int session_id = rand() % 20000 + 1;
        struct sockaddr_in serverForInfo_Addr;
        socklen_t serverForInfo_Addr_len = sizeof(serverForInfo_Addr);
       
        serverForInfo[indexOfClient] = accept(listen_socket, (struct sockaddr *)&serverForInfo_Addr, &serverForInfo_Addr_len);
        if(serverForInfo[indexOfClient] < 0)
        {
            perror("Accept failed");
        }
        sprintf(response, "DianTP/0.5 200 OK\r\nCSeq: 2\r\n%s\r\nSession: %d\r\n\r\n", clientInfo, session_id);
        printf("The information send to the client:\n%s", response);
        send(client_sock, response, strlen(response), 0);
    }
    else if (strcmp(method, "PLAY") == 0)
    {
        char newResponse[MAX_BUFFER_SIZE] = {0};
        strcpy(session_header[indexOfClient], strtok(NULL, "\r\n"));
        char *range = strtok(NULL, "\r\n");
        printf("The client's range is %s\n", range);
        sprintf(newResponse, "DianTP/0.5 200 OK\r\n%s\r\n%s\r\n\r\n", cseq_header, session_header[indexOfClient]);
        printf("The information send to the client:\n%s", response);
        printf("%s", newResponse);
        send(client_sock, newResponse, strlen(newResponse), 0);
        sleep(1);
        char sendinfo[MAX_BUFFER_SIZE] = "You are my cup of tea, my sweet potato pie.\n";
        if(send(serverForInfo[indexOfClient], sendinfo, strlen(sendinfo), 0) < 0)
        {
            perror("send failed");
        }
        sleep(1);
    }
    else if (strcmp(method, "TEARDOWN") == 0)
    {
        char *client_give_session_header = strtok(NULL, "\r\n");
        // printf("%s, %s", client_give_session_header, session_header);
        if (strcmp(client_give_session_header, session_header[indexOfClient]) == 0)
        {
            close(serverForInfo[indexOfClient]);
            close(client_sock);
            printf("close %s's socket successfully\n\n", session_header[indexOfClient]);
        }
        else
        {
            send(serverForInfo[indexOfClient], "DianTP/0.5 400 Bad Request\r\nCSeq: 4\r\n\r\n", MAX_BUFFER_SIZE, 0);
        }
        indexOfClient++;
    }
    else
    {
        char response[MAX_BUFFER_SIZE] = {0};
        sprintf(response, "DianTP/0.5 400 Bad Request\r\nCSeq: 1\r\n\r\n");
        send(client_sock, response, strlen(response), 0);
        printf("Unsupported DianTP request\n");
    }
    memset(buffer, 0, MAX_BUFFER_SIZE);
    printf("DianTP request received and handled successfully\n");
}
void *client_handler(void *);

int main(int argc, char *argv[])
{
    int client_socket;
    struct sockaddr_in server_addr, client_addr, listen_addr;
    pthread_t thread_id;

    // 创建服务器socket
    if ((server_socket = socket(AF_INET, SOCK_STREAM, 0)) == 0)
    {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }
    if ((listen_socket = socket(AF_INET, SOCK_STREAM, 0)) == 0)
    {
        perror("socket failed");
        exit(EXIT_FAILURE);
    }
    
    // 绑定服务器地址
    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = INADDR_ANY;
    server_addr.sin_port = htons(SERVER_PORT);

    if (bind(server_socket, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0)
    {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }
    listen_addr.sin_family = AF_INET;
    listen_addr.sin_addr.s_addr = INADDR_ANY;
    listen_addr.sin_port = htons(LISTEN_PORT);
    if (bind(listen_socket, (struct sockaddr *)&listen_addr, sizeof(server_addr)) < 0)
    {
        perror("bind failed");
        exit(EXIT_FAILURE);
    }

    // 监听客户端连接请求
    if (listen(server_socket, MAX_CLIENTS) < 0)
    {
        perror("listen failed");
        exit(EXIT_FAILURE);
    }
    if (listen(listen_socket, MAX_CLIENTS) < 0)
    {
        perror("listen failed");
        exit(EXIT_FAILURE);
    }
    printf("Server listening on port %d\n", ntohs(server_addr.sin_port));

    while (1)
    {
        int addrlen = sizeof(client_addr);

        // 接受客户端连接请求
        if ((client_socket = accept(server_socket, (struct sockaddr *)&client_addr, (socklen_t *)&addrlen)) < 0)
        {
            perror("accept failed");
            exit(EXIT_FAILURE);
        }

        printf("New client connected: %s:%d\n", inet_ntoa(client_addr.sin_addr), ntohs(client_addr.sin_port));

        // 创建新线程处理客户端请求
        if (pthread_create(&thread_id, NULL, client_handler, (void *)&client_socket) < 0)
        {
            perror("pthread_create failed");
            exit(EXIT_FAILURE);
        }
    }

    return 0;
}

void *client_handler(void *socket_ptr)
{
    int client_socket = *(int *)socket_ptr;

    char buffer[MAX_BUFFER_SIZE];
    while (1)
    {
        int recv_size = recv(client_socket, buffer, MAX_BUFFER_SIZE, 0);
        if (recv_size <= 0)
        {
            printf("Failed to receive data");
            return NULL;
        }
        handle(client_socket, buffer, listen_socket);
    }

    return NULL;
}
